/**
 * JAVACC DEMO 1.0
 * @copy right apache company All rights reserved. 
 * @Package com.apache.rpc.server.protocl  
 */
package com.apache.rpc.client.protocol;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;

import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

import com.apache.api.vo.ResultEntity;
import com.apache.exception.ServiceException;
import com.apache.rpc.util.JsonEntityParese;
import com.apache.rpc.util.MyX509TrustManager;

/**
 * description:  https通信接口实现
 * @author Hou Dayu 创建时间：2014-10-28  
 * @Copyright(c)2014:
 */
public class HttpsProtocolServiceClient extends AbstractProtocolClient {

	private Logger logger = Logger.getLogger(HttpsProtocolServiceClient.class);

	/**
	 * TODO 简单描述该方法的实现功能（可选）.  
	 */
	public ResultEntity doService(String beanId, String methodKey, Map<String, Object> params) {
		String xmlParams = this.buildXml(beanId, methodKey, "https", params);
		ResultEntity resultEntity = null;
		if (null == register) {
			resultEntity = getResultEntity("没有发布待执行的接口信息");
			return resultEntity;
		}
		String httpUrl = register.getAddress();
		try {
			String result = postHttps(httpUrl, xmlParams, "XML");
			if ("".equals(result) || null == result) {
				resultEntity = getResultEntity("接口调用超时");
				return resultEntity;
			}
			resultEntity = JsonEntityParese.instance().toBean(result, ResultEntity.class);
		} catch (ServiceException e) {
			resultEntity = getResultEntity(e.getMessage());
		}
		return resultEntity;
	}

	/**
	 * 公共方法
	 * post http 请求，接受返回的结果xml文档	 
	 * @param url webservice地址
	 * @param parasInput 传递的参数
	 * @return xml类型字符串
	 */
	private String postHttps(String httpsurl, String params, String type) {
		String line = "";
		try {
			StringBuffer buffer = new StringBuffer();
			buffer.append("params=" + params);
			buffer.append("ParamType=" + type);
			buffer.append("&httpRand=" + System.currentTimeMillis());
			SSLSocketFactory ssf = getSSLSocketFactory();
			URL url = new URL(httpsurl);
			HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
			httpUrlConn.setSSLSocketFactory(ssf);

			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			httpUrlConn.setUseCaches(false);

			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod("POST");
			String outputStr = buffer.toString();
			// 当有数据需要提交时
			if (null != outputStr) {
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 注意编码格式，防止中文乱码
				outputStream.write(outputStr.getBytes("UTF-8"));
				outputStream.close();
			}
			// 将返回的输入流转换成字符串
			InputStream inputStream = httpUrlConn.getInputStream();
			int code = httpUrlConn.getResponseCode();
			if (HttpsURLConnection.HTTP_OK == code) { //如果执行成功
				line = IOUtils.toString(inputStream, "UTF-8");
			} else {
				logger.error("HTTP请求响应失败，错误码为：" + code);
			}
			inputStream.close();
		} catch (Exception e) {
			logger.error(e);
		}
		return line;
	}

	private SSLSocketFactory getSSLSocketFactory() throws Exception {
		// 创建SSLContext对象，并使用我们指定的信任管理器初始化
		TrustManager[] tm = { new MyX509TrustManager() };
		SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
		sslContext.init(null, tm, new java.security.SecureRandom());
		// 从上述SSLContext对象中得到SSLSocketFactory对象
		SSLSocketFactory ssf = sslContext.getSocketFactory();
		return ssf;
	}
}
